#region using

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using Pentia.Linq.Mapping;

#endregion

namespace Pentia.Linq
{
  internal class SitecoreQuery<T> : IQueryable<T>
  {
    private readonly IQueryContext _contextData;
    private readonly Expression _expression;
    private readonly QueryContext _queryContext;

    public SitecoreQuery(IQueryContext contextData, Expression expression)
    {
      if (contextData == null)
        throw new ArgumentNullException("contextData");
      if (expression == null)
        throw new ArgumentNullException("expression");
      _contextData = contextData;
      _expression = expression;
      _queryContext = new QueryContext(new DataManager(ContextData.RootItem.Database));
    }

    public IQueryContext ContextData
    {
      get { return _contextData; }
    }

    public QueryContext QueryContext
    {
      get { return _queryContext; }
    }

    private Database Database
    {
      get { return ContextData.RootItem.Database; }
    }

    public TextWriter Log { get; set; }

    #region IQueryable<T> Members

    public IEnumerator<T> GetEnumerator()
    {
      SitecoreQueryParser parser = new SitecoreQueryParser(ContextData, Expression) {Log = Log};
      Query.Query query = parser.Parse();

      object queryResult = query.Execute(QueryContext);
      QueryContext[] contextArray = (queryResult is QueryContext
                                       ? new QueryContext[] {(QueryContext) queryResult}
                                       : (QueryContext[]) queryResult);

      if (contextArray == null)
        yield break;

      int index = 0;
      foreach (QueryContext queryResultItem in contextArray)
      {
        //TODO: Remove this restriction
        if (index++ > 10)
          yield break;
        yield return new SitecoreEntityFactory().Create<T>(Database.Items[queryResultItem.ID]);
      }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return GetEnumerator();
    }

    public Expression Expression
    {
      get { return _expression; }
    }

    public Type ElementType
    {
      get { return typeof (T); }
    }

    public IQueryProvider Provider
    {
      get { return new SitecoreQueryProvider(ContextData); }
    }

    #endregion

  }
}